﻿#include "videorenderer.h"
#include <QOpenGLFramebufferObject>

VideoRenderer::VideoRenderer()
{
    initializeOpenGLFunctions();

    // 创建纹理
    glGenTextures(1, &m_texture);

    // 初始化着色器程序
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
                                      "attribute highp vec4 vertexCoord;"
                                      "attribute highp vec2 textureCoord;"
                                      "varying highp vec2 vTextureCoord;"
                                      "void main() {"
                                      "   gl_Position = vertexCoord;"
                                      "   vTextureCoord = vec2(textureCoord.x, 1.0 - textureCoord.y);"
                                      "}");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
                                      "varying highp vec2 vTextureCoord;"
                                      "uniform sampler2D textureSampler;"
                                      "void main() {"
                                      "   gl_FragColor = texture2D(textureSampler, vTextureCoord);"
                                      "}");

    m_program.link();
}

VideoRenderer::~VideoRenderer()
{
    glDeleteTextures(1, &m_texture);
}

QOpenGLFramebufferObject* VideoRenderer::createFramebufferObject(const QSize &size)
{
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
    return new QOpenGLFramebufferObject(size, format);
}

void VideoRenderer::render()
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    QMutexLocker locker(&m_frameMutex);
    if (m_currentFrame.isNull()) return;

    // 设置纹理
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //RGB888
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                 m_currentFrame.width(), m_currentFrame.height(),
                 0, GL_RGB, GL_UNSIGNED_BYTE, m_currentFrame.bits());

    /*
    //RGBA8888
    //转换图像格式为RGBA8888
    QImage frame = m_currentFrame.convertToFormat(QImage::Format_RGBA8888);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                 frame.width(), frame.height(),
                 0, GL_RGBA, GL_UNSIGNED_BYTE, frame.bits());
    */

    // 启用必要的状态
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // 使用着色器程序
    m_program.bind();

    // 设置顶点和纹理坐标
    GLfloat vertices[] = {
        -1.0f, -1.0f,
        1.0f, -1.0f,
        1.0f,  1.0f,
        -1.0f,  1.0f
    };

    GLfloat texCoords[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        1.0f, 0.0f,
        0.0f, 0.0f
    };

    // 设置顶点属性
    m_program.enableAttributeArray("vertexCoord");
    m_program.setAttributeArray("vertexCoord", vertices, 2);

    m_program.enableAttributeArray("textureCoord");
    m_program.setAttributeArray("textureCoord", texCoords, 2);

    // 设置纹理采样器
    m_program.setUniformValue("textureSampler", 0);

    // 绘制
    glDrawArrays(GL_QUADS, 0, 4);

    // 清理
    m_program.disableAttributeArray("vertexCoord");
    m_program.disableAttributeArray("textureCoord");
    m_program.release();

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

void VideoRenderer::synchronize(QQuickFramebufferObject *item)
{
    Q_UNUSED(item);
    // 可以在这里同步QML属性
}

void VideoRenderer::updateFrame(const QImage &frame)
{
    QMutexLocker locker(&m_frameMutex);
    m_currentFrame = frame;
    m_textureSize = frame.size();
}
